package com.gusto.engine.semsim.measures.impl;

import java.util.Map;

import org.apache.log4j.Logger;

import com.gusto.engine.semsim.exceptions.SimilarityException;
import com.gusto.engine.semsim.measures.ValueSimilarity;

/**
 * <p>Calculates the similarity on the basis of numeric intervals<br/>
 * The intervals are of the form [from, to[.</p>
 * 
 * @author amokrane.belloui@gmail.com
 */
public class IntervalValueSimilarity implements ValueSimilarity {
	
	private Logger log = Logger.getLogger(IntervalValueSimilarity.class);
	
	private Map<String, Double> intervals;
	public void setIntervals(Map<String, Double> intervals) {
		this.intervals = intervals;
	}
	
	public String getId() {
		String id = "[" + getClass().getName() + "|" + intervals + "]";
		return id;
	}
	
	public Double getSimilarity(Object value1, Object value2) throws SimilarityException {
		try {
			Double diff = null;
			if (value1 instanceof Integer && value2 instanceof Integer) {
				diff = ((Integer)value1 - (Integer)value2) * 1.0;
			}
			else if (value1 instanceof Double && value2 instanceof Double) {
				diff = ((Double)value1 - (Double)value2);
			}
			else if (value1 instanceof Long && value2 instanceof Long) {
				diff = ((Long)value1 - (Long)value2) * 1.0;
			}
			else {
				throw new SimilarityException("Types " + value1.getClass() + " " + value2.getClass() + " not supported");
			}
			diff = Math.abs(diff);
			log.debug("Difference is '" + diff + "'");
			try {
				for (String key : intervals.keySet()) {
					Double from = Double.parseDouble(key.substring(0, key.indexOf("-")));
					Double to = Double.parseDouble(key.substring(key.indexOf("-") + 1));
					
					boolean inInterval = (diff >= from) && (diff < to);
					if (inInterval) {
						log.debug("Difference '" + diff + "' in interval '" + from + "'-'" + to + "'");
						log.info("Similarity (" + value1 + " " + value2 + ") = '" + intervals.get(key) + "'");
						return intervals.get(key);
					}
				}
			}
			catch (Exception ex) {
				throw new SimilarityException("Error in configuration");
			}
			return 0.0;
		}
		catch (Exception ex) {
			throw new SimilarityException("This similarity is only applicable on numeric values");
		}
	}
	
}
